package com.xiaoxi.codemodelserver.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxi.codemodelserver.domain.dto.BMSDictDTO;
import com.xiaoxi.codemodelserver.domain.vo.BMSDictTree;
import com.xiaoxi.codemodelserver.domain.vo.BMSDictVO;
import com.xiaoxi.codemodelserver.mapper.BmsDictMapper;
import com.xiaoxi.codemodelserver.service.BmsDictService;
import com.xiaoxi.common.constant.enumeration.dict.TitleLevelEnums;
import com.xiaoxi.common.constant.enumeration.statuscode.user.DictUserEnums;
import com.xiaoxi.common.exception.BMSException;
import com.xiaoxi.domain.quick.BmsDict;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @ClassName BmsDictServiceImpl
 * @Description
 * @Author xiaoxi
 * @Date 2022-11-03
 * @Version 1.0
 */
@Service
@Slf4j
public class BmsDictServiceImpl extends ServiceImpl<BmsDictMapper, BmsDict> implements BmsDictService {

    @Override
    public List<BMSDictTree> findListByTree() {

        QueryWrapper<BmsDict> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("type", 1, 2);
        List<BmsDict> bmsDictList = baseMapper.selectList(queryWrapper);

        // 开始格式化数据
        return calcBMSDictTree(bmsDictList);

    }

    @Override
    public IPage<BmsDict> findListByPage(BMSDictDTO bmsDictDTO, Pageable pageable) throws BMSException {

        QueryWrapper<BmsDict> queryWrapper = new QueryWrapper<>();

        if (StringUtils.isNotBlank(bmsDictDTO.getDictName())) {
            queryWrapper.like("dict_name", bmsDictDTO.getDictName());
        }
        if (StringUtils.isNotBlank(bmsDictDTO.getDictCode())) {
            queryWrapper.like("dict_code", bmsDictDTO.getDictCode());
        }

        if (!TitleLevelEnums.THIRD_TITLE.getCode().equals(bmsDictDTO.getType())) {
            if (Objects.isNull(bmsDictDTO.getType())) {
                queryWrapper.eq("type", 1);
            } else {
                queryWrapper.eq("type", bmsDictDTO.getType() + 1);
            }
        }

        if (Objects.nonNull(bmsDictDTO.getParentId())) {
            queryWrapper.apply("find_in_set({0}, parent_ids)", bmsDictDTO.getParentId());
        }

        IPage<BmsDict> iPage = new Page<>(pageable.getPageNumber(), pageable.getPageSize());
        return baseMapper.selectPage(iPage, queryWrapper);

    }

    @Override
    public void add(BMSDictVO bmsDictVO) throws BMSException {

        BmsDict bmsDict = new BmsDict();
        // 特殊处理，一级标题
        if (0 == bmsDictVO.getParentId()) {
            BeanUtils.copyProperties(bmsDictVO, bmsDict);
            bmsDict.setParentIds("0");
            bmsDict.setType(bmsDict.getParentIds().split(",").length);
            baseMapper.insert(bmsDict);
            return;
        }

        BmsDict parentDict = findById(bmsDictVO.getParentId());

        if (Objects.isNull(parentDict)) {
            throw new BMSException(DictUserEnums.PARENT_ID_IS_NOT_EXIST);
        }

        BeanUtils.copyProperties(bmsDictVO, bmsDict);

        bmsDict.setParentIds(parentDict.getParentIds() + "," + parentDict.getId());

        bmsDict.setType(bmsDict.getParentIds().split(",").length);

        baseMapper.insert(bmsDict);
    }

    @Override
    public void delete(Long id) {

        // 先删除本身
        baseMapper.deleteById(id);

        // 再删除下级
        QueryWrapper<BmsDict> queryWrapper = new QueryWrapper<>();
        queryWrapper.apply("find_in_set({0}, parent_ids)", id);
        baseMapper.delete(queryWrapper);

    }

    @Override
    public void update(BMSDictVO bmsDictVO) throws BMSException {

        BmsDict bmsDict = findById(bmsDictVO.getId());

        if (Objects.isNull(bmsDict)) {
            throw new BMSException(DictUserEnums.PLEASE_CHECK_DICT_ID);
        }

        if (bmsDict.getParentId().equals(bmsDictVO.getParentId())) {
            BeanUtils.copyProperties(bmsDictVO, bmsDict);
            baseMapper.updateById(bmsDict);
        } else {
            throw new BMSException(DictUserEnums.NOT_ALLOW_MODIFY_PARENT);
        }

    }

    @Override
    public BmsDict findById(Long id) {
        return baseMapper.selectById(id);
    }


    /**
     * 计算 字典树
     *
     * @param bmsDictList
     * @return
     */
    private List<BMSDictTree> calcBMSDictTree(List<BmsDict> bmsDictList) {

        // 1. 本来应该是 long -> List  但已经知道是二级，所以直接long -> 对象
        Map<Long, BMSDictTree> bmsDictTreeMap = new HashMap<>();

        // 2. 转前端数据
        List<BMSDictTree> bmsDictTreeList = new ArrayList<>();

        // 一级架构完成
        leaveOne(bmsDictList, bmsDictTreeMap);

        // 二级架构完成
        leaveTwo(bmsDictList, bmsDictTreeMap);

        // 合并数据
        for (Map.Entry<Long, BMSDictTree> bmsDictTreeEntry : bmsDictTreeMap.entrySet()) {
            bmsDictTreeList.add(bmsDictTreeEntry.getValue());
        }

        // 1. 排序
        dfsBMSDictTreeOrderBySort(bmsDictTreeList);

        return bmsDictTreeList;
    }


    /**
     * 完成一级架构
     *
     * @param bmsDictList
     * @param bmsDictTreeMap
     */
    private void leaveOne(List<BmsDict> bmsDictList, Map<Long, BMSDictTree> bmsDictTreeMap) {
        for (BmsDict bmsDict : bmsDictList) {

            if (TitleLevelEnums.FIRST_TITLE.getCode().equals(bmsDict.getType())) {   // 一级标题

                BMSDictTree bmsDictTree = new BMSDictTree();
                bmsDictTree.setId(bmsDict.getId());
                bmsDictTree.setLabel(bmsDict.getDictName());
                bmsDictTree.setParentId(bmsDict.getParentId());
                bmsDictTree.setOrderBy(bmsDict.getOrderBy());
                bmsDictTree.setType(bmsDict.getType());
                bmsDictTree.setChildren(new ArrayList<>());

                bmsDictTreeMap.put(bmsDict.getId(), bmsDictTree);

            }
        }
    }

    /**
     * 完成二级架构
     *
     * @param bmsDictList
     * @param bmsDictTreeMap
     */
    private void leaveTwo(List<BmsDict> bmsDictList, Map<Long, BMSDictTree> bmsDictTreeMap) {
        for (BmsDict bmsDict : bmsDictList) {

            if (TitleLevelEnums.SECOND_TITLE.getCode().equals(bmsDict.getType())) {

                BMSDictTree bmsDictTree = new BMSDictTree();
                bmsDictTree.setId(bmsDict.getId());
                bmsDictTree.setLabel(bmsDict.getDictName());
                bmsDictTree.setParentId(bmsDict.getParentId());
                bmsDictTree.setOrderBy(bmsDict.getOrderBy());
                bmsDictTree.setType(bmsDict.getType());

                bmsDictTree.setChildren(new ArrayList<>());

                BMSDictTree parentDict = bmsDictTreeMap.get(bmsDict.getParentId());
                List<BMSDictTree> childrenDict = parentDict.getChildren();
                childrenDict.add(bmsDictTree);
                parentDict.setChildren(childrenDict);
                bmsDictTreeMap.put(bmsDict.getParentId(), parentDict);

            }

        }
    }

    /**
     * 字典排序
     *
     * @param bmsDictTreeList
     */
    private void dfsBMSDictTreeOrderBySort(List<BMSDictTree> bmsDictTreeList) {
        if (Objects.isNull(bmsDictTreeList) || bmsDictTreeList.size() == 0) {
            return;
        }

        // 1. 排序
        bmsDictTreeList.sort(new Comparator<BMSDictTree>() {
            @Override
            public int compare(BMSDictTree o1, BMSDictTree o2) {
                return o1.getOrderBy() - o2.getOrderBy();
            }
        });

        // 2. 递归取 子菜单
        for (BMSDictTree bmsDictTree : bmsDictTreeList) {
            dfsBMSDictTreeOrderBySort(bmsDictTree.getChildren());
        }
    }

}
